Mukund CPOP analysis

#CPOP data
GSE46474 = getGEO("GSE46474")[[1]]
Found 1 file(s)
GSE46474_series_matrix.txt.gz
GSE36059 = getGEO("GSE36059")[[1]]
Found 1 file(s)
GSE36059_series_matrix.txt.gz
Using locally cached version of GPL570 found here:
C:\Users\lmcca\AppData\Local\Temp\RtmpoVR8T7/GPL570.soft.gz 
GSE48581 = getGEO("GSE48581")[[1]]
Found 1 file(s)
GSE48581_series_matrix.txt.gz
Using locally cached version of GPL570 found here:
C:\Users\lmcca\AppData\Local\Temp\RtmpoVR8T7/GPL570.soft.gz 
# The below is what the user uploads
# GSE129166 = getGEO("GSE129166")[[1]]
# The below is not important
#GSE15296 = getGEO("GSE15296")[[1]]
gene_names = function(gse) {
  fData(gse)$`Gene Symbol` = unlist(lapply(strsplit(fData(gse)$`Gene Symbol`, " /// ", 1), `[`, 1))

  idx = which(!duplicated(fData(gse)$`Gene Symbol`) & !is.na(fData(gse)$`Gene Symbol`))
  gse = gse[idx,]
  rownames(gse) = fData(gse)$`Gene Symbol`
  
  return(gse)
}

GSE46474 = gene_names(GSE46474)
GSE36059 = gene_names(GSE36059)
GSE48581 = gene_names(GSE48581)
pData(GSE46474)
pData(GSE36059)
pData(GSE48581)
## keeping only the 100 most variable genes in my data frame 
exp_GSE36059 = (exprs(GSE36059))
Variance = rowVars(as.matrix(exp_GSE36059))
Variance = as.data.frame(Variance)
exp_GSE36059 = as.data.frame(exp_GSE36059)
exp_GSE36059 = cbind(exp_GSE36059, variance = Variance)
exp_GSE36059 = slice_max(exp_GSE36059, order_by = Variance, n = 2000)
exp_GSE36059 = subset(exp_GSE36059, select = -c(Variance))
row_names_exp_GSE36059 = rownames(exp_GSE36059)


exp_GSE46474 = (exprs(GSE46474))
Variance = rowVars(as.matrix(exp_GSE46474))
Variance = as.data.frame(Variance)
exp_GSE46474 = as.data.frame(exp_GSE46474)
exp_GSE46474 = cbind(exp_GSE46474, variance = Variance)
exp_GSE46474 = slice_max(exp_GSE46474, order_by = Variance, n = 2000)
exp_GSE46474 = subset(exp_GSE46474, select = -c(Variance))
row_names_exp_GSE46474 = rownames(exp_GSE46474)


exp_GSE48581 = (exprs(GSE48581))
Variance = rowVars(as.matrix(exp_GSE48581))
Variance = as.data.frame(Variance)
exp_GSE48581 = as.data.frame(exp_GSE48581)
exp_GSE48581 = cbind(exp_GSE48581, variance = Variance)
exp_GSE48581 = slice_max(exp_GSE48581, order_by = Variance, n = 2000)
exp_GSE48581 = subset(exp_GSE48581, select = -c(Variance))
row_names_exp_GSE48581 = rownames(exp_GSE48581)


intersection = intersect(row_names_exp_GSE36059, row_names_exp_GSE46474)
intersection = intersect(intersection, row_names_exp_GSE48581)

exp_GSE36059 = as.data.frame(t(as.matrix(exp_GSE36059)))
exp_GSE36059 = subset(exp_GSE36059, select = c(intersection))

exp_GSE46474 = as.data.frame(t(as.matrix(exp_GSE46474)))
exp_GSE46474 = subset(exp_GSE46474, select = c(intersection))

exp_GSE48581 = as.data.frame(t(as.matrix(exp_GSE48581)))
exp_GSE48581 = subset(exp_GSE48581, select = c(intersection))

GSE36059_id <- data.frame("Dataset" = rep("GSE36059",nrow(exp_GSE36059)))
GSE46474_id <- data.frame("Dataset" = rep("GSE46474",nrow(exp_GSE46474)))
GSE48581_id <- data.frame("Dataset" = rep("GSE48581",nrow(exp_GSE48581)))

z1 = exp_GSE36059 %>% as.matrix()
z3 = exp_GSE46474 %>% as.matrix()
z2 = exp_GSE48581 %>% as.matrix()

## arcsine transformation

exp_GSE36059_arc <- exp_GSE36059
exp_GSE36059_arc = exp_GSE36059_arc / max(exp_GSE36059_arc)
exp_GSE36059_arc = asin(sqrt(exp_GSE36059_arc))

exp_GSE46474_arc <- exp_GSE46474
exp_GSE46474_arc = exp_GSE46474_arc / max(exp_GSE46474_arc)
exp_GSE46474_arc = asin(sqrt(exp_GSE46474_arc))

exp_GSE48581_arc <- exp_GSE48581
exp_GSE48581_arc = exp_GSE48581_arc / max(exp_GSE48581_arc)
exp_GSE48581_arc = asin(sqrt(exp_GSE48581_arc))

z1_pairwise = pairwise_col_diff(z1) %>% as.matrix()
z2_pairwise = pairwise_col_diff(z2) %>% as.matrix()
z3_pairwise = pairwise_col_diff(z3) %>% as.matrix()


z1_arc = pairwise_col_diff(exp_GSE36059_arc) %>% as.matrix()
z3_arc = pairwise_col_diff(exp_GSE46474_arc) %>% as.matrix()
z2_arc = pairwise_col_diff(exp_GSE48581_arc) %>% as.matrix()

## log transform

exp_GSE36059_log <- exp_GSE36059
exp_GSE36059_log = exp_GSE36059_log + 1
exp_GSE36059_log = log(exp_GSE36059_log)

exp_GSE46474_log <- exp_GSE46474
exp_GSE46474_log = exp_GSE46474_log + 1
exp_GSE46474_log = log(exp_GSE46474_log)

exp_GSE48581_log <- exp_GSE48581
exp_GSE48581_log = exp_GSE48581_log + 1
exp_GSE48581_log = log(exp_GSE48581_log)

z1_log = exp_GSE36059_log  %>% as.matrix()
z3_log = exp_GSE46474_log %>% as.matrix()
z2_log = exp_GSE48581_log %>% as.matrix()

# View(z1_log)

getting the results vectors

p_GSE46474 = pData(GSE46474)
p_GSE48581 = pData(GSE48581) 
p_GSE36059 = pData(GSE36059) 

p_GSE36059$diagnosis = ifelse(p_GSE36059$characteristics_ch1 == "diagnosis: non-rejecting", 0, 1)
p_GSE48581$diagnosis = ifelse(p_GSE48581$characteristics_ch1.1 == "diagnosis (tcmr, abmr, mixed, non-rejecting, nephrectomy): non-rejecting", 0, 1)
p_GSE46474$diagnosis = ifelse(p_GSE46474$characteristics_ch1.5 == "procedure status: post-transplant non-rejection (NR)", 0, 1)

y1 = as.factor(p_GSE36059$diagnosis)
y2 = as.factor(p_GSE48581$diagnosis)
y3 = as.factor(p_GSE46474$diagnosis)
### GSE36059
### GSE48581
# these have reject + stable but categorized in more detail -> either have more groups that we are predicting, or we could do purely binary 

Predicting Gender

z1_pairwise = data.frame(pairwise_col_diff(z1_log) %>% as.matrix())
z2_pairwise = data.frame(pairwise_col_diff(z2_log) %>% as.matrix())
z3_pairwise = data.frame(pairwise_col_diff(z3_log) %>% as.matrix())
z3_pairwise
p_GSE46474 = pData(GSE46474)
p_GSE46474$outcome = ifelse(p_GSE46474$characteristics_ch1.1 == "Sex: M", 0, 1)
p_GSE46474
pairwise_preprocess = function(exp_GSE, top_x) {
  Variance = rowVars(as.matrix(exp_GSE))
  Variance = as.data.frame(Variance)
  exp_GSE = as.data.frame(exp_GSE)
  exp_GSE = cbind(exp_GSE, variance = Variance)
  exp_GSE = slice_max(exp_GSE, order_by = Variance, n = top_x)
  exp_GSE = subset(exp_GSE, select = -c(Variance))
  row_names_exp_GSE = rownames(exp_GSE)
  exp_GSE = as.data.frame(t(as.matrix(exp_GSE)))
  
  return(exp_GSE)
}
pairwise = function(exp_GSE, intersection, transform_type) {
  
  #exp_GSE = subset(exp_GSE, select = c(intersection))
  
  z = exp_GSE
  
  if (transform_type == "Arc") {
    z = z / max(z)
    z = asin(sqrt(z))
    z = pairwise_col_diff(z) %>% as.matrix()
  }
  else if (transform_type == "Log") {
    z = z + 1
    z = log(z)
    z = pairwise_col_diff(z) %>% as.matrix()
  }
  else if (transform_type == "Pair"){
    z = z %>% as.matrix()
    z_pairwise = pairwise_col_diff(z) %>% as.matrix()
    
  }
  z = data.frame(z)
  
  return(z)
}
z = pairwise_preprocess(exprs(GSE46474), 50)
known_genes = c("XIST", "EIF1AY", "ANKRD44")
z = z %>% select(known_genes) 
Note: Using an external vector in selections is ambiguous.
i Use `all_of(known_genes)` instead of `known_genes` to silence this message.
i See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
This message is displayed once per session.
z = pairwise(z, NULL, "Log")
z
test1 = data.frame(z1) %>% select(known_genes)
test2 = data.frame(z2) %>% select(known_genes)

test1 = pairwise(test1, NULL, "Log")
test2 = pairwise(test2, NULL, "Log")

outcome1 = knn(z, test1, p_GSE46474$outcome, k=3)
outcome2 = knn(z, test2, p_GSE46474$outcome, k=3)

p_GSE46474$outcome
 [1] 0 0 1 1 1 0 0 1 0 1 0 0 0 0 0 1 0 1 0 0 0 1 0 0 1 0 1 1 0 1 0 0 0 0 0 0 1 0 1 0
z1_pairwise$outcome = y1
z2_pairwise$outcome = y2
z3_pairwise$outcome = y3

z1_pairwise$dataset = "GSE36059"
z2_pairwise$dataset = "GSE48581"
z3_pairwise$dataset = "GSE46474"

z1_pairwise$gender_outcome = outcome1
z2_pairwise$gender_outcome = outcome2
z3_pairwise$gender_outcome = as.factor(p_GSE46474$outcome)
z1_pairwise
joined = union(union(z1_pairwise, z2_pairwise), z3_pairwise)
joined
write.csv(joined, "combined_dataset.csv")
# Assumes input dataframe is already sanitized
calculate_gender = function(dataframe) {
  colnames(dataframe) = lower(colnames(dataframe))
  outcome = NULL
  if ("outcome" %in% colnames(dataframe)) {
    outcome = dataframe$outcome
    dataframe = select(dataframe, -one_of("outcome"))
}
  if ("xist" %in% colnames(dataframe) && "eif1ay" %in% colnames(dataframe) && "ankrd44" %in% colnames(dataframe)) {
    outcome_df = dataframe %>% select(xist, eif1ay, ankrd44)
    outcome_df = dataframe + 1
    outcome_df = log(outcome_df)
    outcome_df = pairwise_col_diff(outcome_df) %>% as.matrix()
    outcome_df = data.frame(outcome_df)
    
    # Can replace this with an already preprocessed dataframe
    known_genes = c("xist", "eif1ay", "ankrd44")
    p_GSE46474 = pData(GSE46474)
    p_GSE46474$outcome = ifelse(p_GSE46474$characteristics_ch1.1 == "Sex: M", 0, 1)
    exprs_GSE46474 = data.frame(t(exprs(GSE46474)))
    colnames(exprs_GSE46474) = lower(colnames(exprs_GSE46474))
    exprs_GSE46474 = exprs_GSE46474 %>% select(known_genes)
    exprs_GSE46474 = exprs_GSE46474 + 1
    exprs_GSE46474 = log(exprs_GSE46474)
    exprs_GSE46474 = pairwise(exprs_GSE46474) %>% as.matrix()
    exprs_GSE46474 = data.frame(exprs_GSE46474)
    
    model = knn(exprs_GSE46474, outcome_df, p_GSE46474$outcome, k = 3)
    
    dataframe$gender = model
    dataframe$outcome = outcome
    
    return(dataframe)
    
  }
}
# Show boxplot for expression levels for each gene split by source dataset
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7ciwgaW5jbHVkZT1GQUxTRX0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeSh0dW5lUikNCmxpYnJhcnkoZGV2dG9vbHMpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHRzZmVhdHVyZXMpDQpsaWJyYXJ5KGNsYXNzKQ0KbGlicmFyeShjdlRvb2xzKQ0KbGlicmFyeShyYW5kb21Gb3Jlc3QpDQpsaWJyYXJ5KEdFT3F1ZXJ5KSANCmxpYnJhcnkoUi51dGlscykNCmxpYnJhcnkocmVzaGFwZTIpDQpsaWJyYXJ5KGxpbW1hKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoZTEwNzEpDQpsaWJyYXJ5KERUKQ0KbGlicmFyeSh2aXJpZGlzKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KHNjYWxlcykNCmxpYnJhcnkoQ1BPUCkNCmxpYnJhcnkobWF0cml4U3RhdHMpDQpsaWJyYXJ5KHZpc05ldHdvcmspDQpgYGANCg0KIyMgTXVrdW5kIENQT1AgYW5hbHlzaXMgDQpgYGB7cn0NCiNDUE9QIGRhdGENCkdTRTQ2NDc0ID0gZ2V0R0VPKCJHU0U0NjQ3NCIpW1sxXV0NCkdTRTM2MDU5ID0gZ2V0R0VPKCJHU0UzNjA1OSIpW1sxXV0NCkdTRTQ4NTgxID0gZ2V0R0VPKCJHU0U0ODU4MSIpW1sxXV0NCg0KDQojIFRoZSBiZWxvdyBpcyB3aGF0IHRoZSB1c2VyIHVwbG9hZHMNCiMgR1NFMTI5MTY2ID0gZ2V0R0VPKCJHU0UxMjkxNjYiKVtbMV1dDQojIFRoZSBiZWxvdyBpcyBub3QgaW1wb3J0YW50DQojR1NFMTUyOTYgPSBnZXRHRU8oIkdTRTE1Mjk2IilbWzFdXQ0KYGBgDQoNCg0KYGBge3J9DQpnZW5lX25hbWVzID0gZnVuY3Rpb24oZ3NlKSB7DQogIGZEYXRhKGdzZSkkYEdlbmUgU3ltYm9sYCA9IHVubGlzdChsYXBwbHkoc3Ryc3BsaXQoZkRhdGEoZ3NlKSRgR2VuZSBTeW1ib2xgLCAiIC8vLyAiLCAxKSwgYFtgLCAxKSkNCg0KICBpZHggPSB3aGljaCghZHVwbGljYXRlZChmRGF0YShnc2UpJGBHZW5lIFN5bWJvbGApICYgIWlzLm5hKGZEYXRhKGdzZSkkYEdlbmUgU3ltYm9sYCkpDQogIGdzZSA9IGdzZVtpZHgsXQ0KICByb3duYW1lcyhnc2UpID0gZkRhdGEoZ3NlKSRgR2VuZSBTeW1ib2xgDQogIA0KICByZXR1cm4oZ3NlKQ0KfQ0KDQpHU0U0NjQ3NCA9IGdlbmVfbmFtZXMoR1NFNDY0NzQpDQpHU0UzNjA1OSA9IGdlbmVfbmFtZXMoR1NFMzYwNTkpDQpHU0U0ODU4MSA9IGdlbmVfbmFtZXMoR1NFNDg1ODEpDQpgYGANCg0KYGBge3J9DQpwRGF0YShHU0U0NjQ3NCkNCnBEYXRhKEdTRTM2MDU5KQ0KcERhdGEoR1NFNDg1ODEpDQpgYGANCg0KDQpgYGB7cn0NCiMjIGtlZXBpbmcgb25seSB0aGUgMTAwIG1vc3QgdmFyaWFibGUgZ2VuZXMgaW4gbXkgZGF0YSBmcmFtZSANCmV4cF9HU0UzNjA1OSA9IChleHBycyhHU0UzNjA1OSkpDQpWYXJpYW5jZSA9IHJvd1ZhcnMoYXMubWF0cml4KGV4cF9HU0UzNjA1OSkpDQpWYXJpYW5jZSA9IGFzLmRhdGEuZnJhbWUoVmFyaWFuY2UpDQpleHBfR1NFMzYwNTkgPSBhcy5kYXRhLmZyYW1lKGV4cF9HU0UzNjA1OSkNCmV4cF9HU0UzNjA1OSA9IGNiaW5kKGV4cF9HU0UzNjA1OSwgdmFyaWFuY2UgPSBWYXJpYW5jZSkNCmV4cF9HU0UzNjA1OSA9IHNsaWNlX21heChleHBfR1NFMzYwNTksIG9yZGVyX2J5ID0gVmFyaWFuY2UsIG4gPSAyMDAwKQ0KZXhwX0dTRTM2MDU5ID0gc3Vic2V0KGV4cF9HU0UzNjA1OSwgc2VsZWN0ID0gLWMoVmFyaWFuY2UpKQ0Kcm93X25hbWVzX2V4cF9HU0UzNjA1OSA9IHJvd25hbWVzKGV4cF9HU0UzNjA1OSkNCg0KDQpleHBfR1NFNDY0NzQgPSAoZXhwcnMoR1NFNDY0NzQpKQ0KVmFyaWFuY2UgPSByb3dWYXJzKGFzLm1hdHJpeChleHBfR1NFNDY0NzQpKQ0KVmFyaWFuY2UgPSBhcy5kYXRhLmZyYW1lKFZhcmlhbmNlKQ0KZXhwX0dTRTQ2NDc0ID0gYXMuZGF0YS5mcmFtZShleHBfR1NFNDY0NzQpDQpleHBfR1NFNDY0NzQgPSBjYmluZChleHBfR1NFNDY0NzQsIHZhcmlhbmNlID0gVmFyaWFuY2UpDQpleHBfR1NFNDY0NzQgPSBzbGljZV9tYXgoZXhwX0dTRTQ2NDc0LCBvcmRlcl9ieSA9IFZhcmlhbmNlLCBuID0gMjAwMCkNCmV4cF9HU0U0NjQ3NCA9IHN1YnNldChleHBfR1NFNDY0NzQsIHNlbGVjdCA9IC1jKFZhcmlhbmNlKSkNCnJvd19uYW1lc19leHBfR1NFNDY0NzQgPSByb3duYW1lcyhleHBfR1NFNDY0NzQpDQoNCg0KZXhwX0dTRTQ4NTgxID0gKGV4cHJzKEdTRTQ4NTgxKSkNClZhcmlhbmNlID0gcm93VmFycyhhcy5tYXRyaXgoZXhwX0dTRTQ4NTgxKSkNClZhcmlhbmNlID0gYXMuZGF0YS5mcmFtZShWYXJpYW5jZSkNCmV4cF9HU0U0ODU4MSA9IGFzLmRhdGEuZnJhbWUoZXhwX0dTRTQ4NTgxKQ0KZXhwX0dTRTQ4NTgxID0gY2JpbmQoZXhwX0dTRTQ4NTgxLCB2YXJpYW5jZSA9IFZhcmlhbmNlKQ0KZXhwX0dTRTQ4NTgxID0gc2xpY2VfbWF4KGV4cF9HU0U0ODU4MSwgb3JkZXJfYnkgPSBWYXJpYW5jZSwgbiA9IDIwMDApDQpleHBfR1NFNDg1ODEgPSBzdWJzZXQoZXhwX0dTRTQ4NTgxLCBzZWxlY3QgPSAtYyhWYXJpYW5jZSkpDQpyb3dfbmFtZXNfZXhwX0dTRTQ4NTgxID0gcm93bmFtZXMoZXhwX0dTRTQ4NTgxKQ0KDQoNCmludGVyc2VjdGlvbiA9IGludGVyc2VjdChyb3dfbmFtZXNfZXhwX0dTRTM2MDU5LCByb3dfbmFtZXNfZXhwX0dTRTQ2NDc0KQ0KaW50ZXJzZWN0aW9uID0gaW50ZXJzZWN0KGludGVyc2VjdGlvbiwgcm93X25hbWVzX2V4cF9HU0U0ODU4MSkNCg0KZXhwX0dTRTM2MDU5ID0gYXMuZGF0YS5mcmFtZSh0KGFzLm1hdHJpeChleHBfR1NFMzYwNTkpKSkNCmV4cF9HU0UzNjA1OSA9IHN1YnNldChleHBfR1NFMzYwNTksIHNlbGVjdCA9IGMoaW50ZXJzZWN0aW9uKSkNCg0KZXhwX0dTRTQ2NDc0ID0gYXMuZGF0YS5mcmFtZSh0KGFzLm1hdHJpeChleHBfR1NFNDY0NzQpKSkNCmV4cF9HU0U0NjQ3NCA9IHN1YnNldChleHBfR1NFNDY0NzQsIHNlbGVjdCA9IGMoaW50ZXJzZWN0aW9uKSkNCg0KZXhwX0dTRTQ4NTgxID0gYXMuZGF0YS5mcmFtZSh0KGFzLm1hdHJpeChleHBfR1NFNDg1ODEpKSkNCmV4cF9HU0U0ODU4MSA9IHN1YnNldChleHBfR1NFNDg1ODEsIHNlbGVjdCA9IGMoaW50ZXJzZWN0aW9uKSkNCg0KR1NFMzYwNTlfaWQgPC0gZGF0YS5mcmFtZSgiRGF0YXNldCIgPSByZXAoIkdTRTM2MDU5Iixucm93KGV4cF9HU0UzNjA1OSkpKQ0KR1NFNDY0NzRfaWQgPC0gZGF0YS5mcmFtZSgiRGF0YXNldCIgPSByZXAoIkdTRTQ2NDc0Iixucm93KGV4cF9HU0U0NjQ3NCkpKQ0KR1NFNDg1ODFfaWQgPC0gZGF0YS5mcmFtZSgiRGF0YXNldCIgPSByZXAoIkdTRTQ4NTgxIixucm93KGV4cF9HU0U0ODU4MSkpKQ0KDQp6MSA9IGV4cF9HU0UzNjA1OSAlPiUgYXMubWF0cml4KCkNCnozID0gZXhwX0dTRTQ2NDc0ICU+JSBhcy5tYXRyaXgoKQ0KejIgPSBleHBfR1NFNDg1ODEgJT4lIGFzLm1hdHJpeCgpDQoNCiMjIGFyY3NpbmUgdHJhbnNmb3JtYXRpb24NCg0KZXhwX0dTRTM2MDU5X2FyYyA8LSBleHBfR1NFMzYwNTkNCmV4cF9HU0UzNjA1OV9hcmMgPSBleHBfR1NFMzYwNTlfYXJjIC8gbWF4KGV4cF9HU0UzNjA1OV9hcmMpDQpleHBfR1NFMzYwNTlfYXJjID0gYXNpbihzcXJ0KGV4cF9HU0UzNjA1OV9hcmMpKQ0KDQpleHBfR1NFNDY0NzRfYXJjIDwtIGV4cF9HU0U0NjQ3NA0KZXhwX0dTRTQ2NDc0X2FyYyA9IGV4cF9HU0U0NjQ3NF9hcmMgLyBtYXgoZXhwX0dTRTQ2NDc0X2FyYykNCmV4cF9HU0U0NjQ3NF9hcmMgPSBhc2luKHNxcnQoZXhwX0dTRTQ2NDc0X2FyYykpDQoNCmV4cF9HU0U0ODU4MV9hcmMgPC0gZXhwX0dTRTQ4NTgxDQpleHBfR1NFNDg1ODFfYXJjID0gZXhwX0dTRTQ4NTgxX2FyYyAvIG1heChleHBfR1NFNDg1ODFfYXJjKQ0KZXhwX0dTRTQ4NTgxX2FyYyA9IGFzaW4oc3FydChleHBfR1NFNDg1ODFfYXJjKSkNCg0KejFfcGFpcndpc2UgPSBwYWlyd2lzZV9jb2xfZGlmZih6MSkgJT4lIGFzLm1hdHJpeCgpDQp6Ml9wYWlyd2lzZSA9IHBhaXJ3aXNlX2NvbF9kaWZmKHoyKSAlPiUgYXMubWF0cml4KCkNCnozX3BhaXJ3aXNlID0gcGFpcndpc2VfY29sX2RpZmYoejMpICU+JSBhcy5tYXRyaXgoKQ0KDQoNCnoxX2FyYyA9IHBhaXJ3aXNlX2NvbF9kaWZmKGV4cF9HU0UzNjA1OV9hcmMpICU+JSBhcy5tYXRyaXgoKQ0KejNfYXJjID0gcGFpcndpc2VfY29sX2RpZmYoZXhwX0dTRTQ2NDc0X2FyYykgJT4lIGFzLm1hdHJpeCgpDQp6Ml9hcmMgPSBwYWlyd2lzZV9jb2xfZGlmZihleHBfR1NFNDg1ODFfYXJjKSAlPiUgYXMubWF0cml4KCkNCg0KIyMgbG9nIHRyYW5zZm9ybQ0KDQpleHBfR1NFMzYwNTlfbG9nIDwtIGV4cF9HU0UzNjA1OQ0KZXhwX0dTRTM2MDU5X2xvZyA9IGV4cF9HU0UzNjA1OV9sb2cgKyAxDQpleHBfR1NFMzYwNTlfbG9nID0gbG9nKGV4cF9HU0UzNjA1OV9sb2cpDQoNCmV4cF9HU0U0NjQ3NF9sb2cgPC0gZXhwX0dTRTQ2NDc0DQpleHBfR1NFNDY0NzRfbG9nID0gZXhwX0dTRTQ2NDc0X2xvZyArIDENCmV4cF9HU0U0NjQ3NF9sb2cgPSBsb2coZXhwX0dTRTQ2NDc0X2xvZykNCg0KZXhwX0dTRTQ4NTgxX2xvZyA8LSBleHBfR1NFNDg1ODENCmV4cF9HU0U0ODU4MV9sb2cgPSBleHBfR1NFNDg1ODFfbG9nICsgMQ0KZXhwX0dTRTQ4NTgxX2xvZyA9IGxvZyhleHBfR1NFNDg1ODFfbG9nKQ0KDQp6MV9sb2cgPSBleHBfR1NFMzYwNTlfbG9nICAlPiUgYXMubWF0cml4KCkNCnozX2xvZyA9IGV4cF9HU0U0NjQ3NF9sb2cgJT4lIGFzLm1hdHJpeCgpDQp6Ml9sb2cgPSBleHBfR1NFNDg1ODFfbG9nICU+JSBhcy5tYXRyaXgoKQ0KDQojIFZpZXcoejFfbG9nKQ0KYGBgDQoNCg0KDQojIyBnZXR0aW5nIHRoZSByZXN1bHRzIHZlY3RvcnMgDQpgYGB7cn0NCnBfR1NFNDY0NzQgPSBwRGF0YShHU0U0NjQ3NCkNCnBfR1NFNDg1ODEgPSBwRGF0YShHU0U0ODU4MSkgDQpwX0dTRTM2MDU5ID0gcERhdGEoR1NFMzYwNTkpIA0KDQpwX0dTRTM2MDU5JGRpYWdub3NpcyA9IGlmZWxzZShwX0dTRTM2MDU5JGNoYXJhY3RlcmlzdGljc19jaDEgPT0gImRpYWdub3Npczogbm9uLXJlamVjdGluZyIsIDAsIDEpDQpwX0dTRTQ4NTgxJGRpYWdub3NpcyA9IGlmZWxzZShwX0dTRTQ4NTgxJGNoYXJhY3RlcmlzdGljc19jaDEuMSA9PSAiZGlhZ25vc2lzICh0Y21yLCBhYm1yLCBtaXhlZCwgbm9uLXJlamVjdGluZywgbmVwaHJlY3RvbXkpOiBub24tcmVqZWN0aW5nIiwgMCwgMSkNCnBfR1NFNDY0NzQkZGlhZ25vc2lzID0gaWZlbHNlKHBfR1NFNDY0NzQkY2hhcmFjdGVyaXN0aWNzX2NoMS41ID09ICJwcm9jZWR1cmUgc3RhdHVzOiBwb3N0LXRyYW5zcGxhbnQgbm9uLXJlamVjdGlvbiAoTlIpIiwgMCwgMSkNCg0KeTEgPSBhcy5mYWN0b3IocF9HU0UzNjA1OSRkaWFnbm9zaXMpDQp5MiA9IGFzLmZhY3RvcihwX0dTRTQ4NTgxJGRpYWdub3NpcykNCnkzID0gYXMuZmFjdG9yKHBfR1NFNDY0NzQkZGlhZ25vc2lzKQ0KIyMjIEdTRTM2MDU5DQojIyMgR1NFNDg1ODENCiMgdGhlc2UgaGF2ZSByZWplY3QgKyBzdGFibGUgYnV0IGNhdGVnb3JpemVkIGluIG1vcmUgZGV0YWlsIC0+IGVpdGhlciBoYXZlIG1vcmUgZ3JvdXBzIHRoYXQgd2UgYXJlIHByZWRpY3RpbmcsIG9yIHdlIGNvdWxkIGRvIHB1cmVseSBiaW5hcnkgDQpgYGANCg0KIyMgUHJlZGljdGluZyBHZW5kZXINCmBgYHtyfQ0KejFfcGFpcndpc2UgPSBkYXRhLmZyYW1lKHBhaXJ3aXNlX2NvbF9kaWZmKHoxX2xvZykgJT4lIGFzLm1hdHJpeCgpKQ0KejJfcGFpcndpc2UgPSBkYXRhLmZyYW1lKHBhaXJ3aXNlX2NvbF9kaWZmKHoyX2xvZykgJT4lIGFzLm1hdHJpeCgpKQ0KejNfcGFpcndpc2UgPSBkYXRhLmZyYW1lKHBhaXJ3aXNlX2NvbF9kaWZmKHozX2xvZykgJT4lIGFzLm1hdHJpeCgpKQ0KejNfcGFpcndpc2UNCmBgYA0KYGBge3J9DQpwX0dTRTQ2NDc0ID0gcERhdGEoR1NFNDY0NzQpDQpwX0dTRTQ2NDc0JG91dGNvbWUgPSBpZmVsc2UocF9HU0U0NjQ3NCRjaGFyYWN0ZXJpc3RpY3NfY2gxLjEgPT0gIlNleDogTSIsIDAsIDEpDQpwX0dTRTQ2NDc0DQpgYGANCg0KYGBge3J9DQpwYWlyd2lzZV9wcmVwcm9jZXNzID0gZnVuY3Rpb24oZXhwX0dTRSwgdG9wX3gpIHsNCiAgVmFyaWFuY2UgPSByb3dWYXJzKGFzLm1hdHJpeChleHBfR1NFKSkNCiAgVmFyaWFuY2UgPSBhcy5kYXRhLmZyYW1lKFZhcmlhbmNlKQ0KICBleHBfR1NFID0gYXMuZGF0YS5mcmFtZShleHBfR1NFKQ0KICBleHBfR1NFID0gY2JpbmQoZXhwX0dTRSwgdmFyaWFuY2UgPSBWYXJpYW5jZSkNCiAgZXhwX0dTRSA9IHNsaWNlX21heChleHBfR1NFLCBvcmRlcl9ieSA9IFZhcmlhbmNlLCBuID0gdG9wX3gpDQogIGV4cF9HU0UgPSBzdWJzZXQoZXhwX0dTRSwgc2VsZWN0ID0gLWMoVmFyaWFuY2UpKQ0KICByb3dfbmFtZXNfZXhwX0dTRSA9IHJvd25hbWVzKGV4cF9HU0UpDQogIGV4cF9HU0UgPSBhcy5kYXRhLmZyYW1lKHQoYXMubWF0cml4KGV4cF9HU0UpKSkNCiAgDQogIHJldHVybihleHBfR1NFKQ0KfQ0KYGBgDQoNCmBgYHtyfQ0KcGFpcndpc2UgPSBmdW5jdGlvbihleHBfR1NFLCBpbnRlcnNlY3Rpb24sIHRyYW5zZm9ybV90eXBlKSB7DQogIA0KICAjZXhwX0dTRSA9IHN1YnNldChleHBfR1NFLCBzZWxlY3QgPSBjKGludGVyc2VjdGlvbikpDQogIA0KICB6ID0gZXhwX0dTRQ0KICANCiAgaWYgKHRyYW5zZm9ybV90eXBlID09ICJBcmMiKSB7DQogICAgeiA9IHogLyBtYXgoeikNCiAgICB6ID0gYXNpbihzcXJ0KHopKQ0KICAgIHogPSBwYWlyd2lzZV9jb2xfZGlmZih6KSAlPiUgYXMubWF0cml4KCkNCiAgfQ0KICBlbHNlIGlmICh0cmFuc2Zvcm1fdHlwZSA9PSAiTG9nIikgew0KICAgIHogPSB6ICsgMQ0KICAgIHogPSBsb2coeikNCiAgICB6ID0gcGFpcndpc2VfY29sX2RpZmYoeikgJT4lIGFzLm1hdHJpeCgpDQogIH0NCiAgZWxzZSBpZiAodHJhbnNmb3JtX3R5cGUgPT0gIlBhaXIiKXsNCiAgICB6ID0geiAlPiUgYXMubWF0cml4KCkNCiAgICB6X3BhaXJ3aXNlID0gcGFpcndpc2VfY29sX2RpZmYoeikgJT4lIGFzLm1hdHJpeCgpDQogICAgDQogIH0NCiAgeiA9IGRhdGEuZnJhbWUoeikNCiAgDQogIHJldHVybih6KQ0KfQ0KYGBgDQoNCmBgYHtyfQ0KeiA9IHBhaXJ3aXNlX3ByZXByb2Nlc3MoZXhwcnMoR1NFNDY0NzQpLCA1MCkNCmtub3duX2dlbmVzID0gYygiWElTVCIsICJFSUYxQVkiLCAiQU5LUkQ0NCIpDQp6ID0geiAlPiUgc2VsZWN0KGtub3duX2dlbmVzKSANCnogPSBwYWlyd2lzZSh6LCBOVUxMLCAiTG9nIikNCnoNCmBgYA0KYGBge3J9DQp0ZXN0MSA9IGRhdGEuZnJhbWUoejEpICU+JSBzZWxlY3Qoa25vd25fZ2VuZXMpDQp0ZXN0MiA9IGRhdGEuZnJhbWUoejIpICU+JSBzZWxlY3Qoa25vd25fZ2VuZXMpDQoNCnRlc3QxID0gcGFpcndpc2UodGVzdDEsIE5VTEwsICJMb2ciKQ0KdGVzdDIgPSBwYWlyd2lzZSh0ZXN0MiwgTlVMTCwgIkxvZyIpDQoNCm91dGNvbWUxID0ga25uKHosIHRlc3QxLCBwX0dTRTQ2NDc0JG91dGNvbWUsIGs9MykNCm91dGNvbWUyID0ga25uKHosIHRlc3QyLCBwX0dTRTQ2NDc0JG91dGNvbWUsIGs9MykNCg0KcF9HU0U0NjQ3NCRvdXRjb21lDQpgYGANCg0KDQpgYGB7cn0NCnoxX3BhaXJ3aXNlJG91dGNvbWUgPSB5MQ0KejJfcGFpcndpc2Ukb3V0Y29tZSA9IHkyDQp6M19wYWlyd2lzZSRvdXRjb21lID0geTMNCg0KejFfcGFpcndpc2UkZGF0YXNldCA9ICJHU0UzNjA1OSINCnoyX3BhaXJ3aXNlJGRhdGFzZXQgPSAiR1NFNDg1ODEiDQp6M19wYWlyd2lzZSRkYXRhc2V0ID0gIkdTRTQ2NDc0Ig0KDQp6MV9wYWlyd2lzZSRnZW5kZXJfb3V0Y29tZSA9IG91dGNvbWUxDQp6Ml9wYWlyd2lzZSRnZW5kZXJfb3V0Y29tZSA9IG91dGNvbWUyDQp6M19wYWlyd2lzZSRnZW5kZXJfb3V0Y29tZSA9IGFzLmZhY3RvcihwX0dTRTQ2NDc0JG91dGNvbWUpDQpgYGANCg0KYGBge3J9DQp6MV9wYWlyd2lzZQ0KYGBgDQoNCg0KYGBge3J9DQpqb2luZWQgPSB1bmlvbih1bmlvbih6MV9wYWlyd2lzZSwgejJfcGFpcndpc2UpLCB6M19wYWlyd2lzZSkNCmpvaW5lZA0KYGBgDQpgYGB7cn0NCndyaXRlLmNzdihqb2luZWQsICJjb21iaW5lZF9kYXRhc2V0LmNzdiIpDQpgYGANCg0KDQpgYGB7cn0NCiMgQXNzdW1lcyBpbnB1dCBkYXRhZnJhbWUgaXMgYWxyZWFkeSBzYW5pdGl6ZWQNCmNhbGN1bGF0ZV9nZW5kZXIgPSBmdW5jdGlvbihkYXRhZnJhbWUpIHsNCiAgY29sbmFtZXMoZGF0YWZyYW1lKSA9IGxvd2VyKGNvbG5hbWVzKGRhdGFmcmFtZSkpDQogIG91dGNvbWUgPSBOVUxMDQogIGlmICgib3V0Y29tZSIgJWluJSBjb2xuYW1lcyhkYXRhZnJhbWUpKSB7DQogICAgb3V0Y29tZSA9IGRhdGFmcmFtZSRvdXRjb21lDQogICAgZGF0YWZyYW1lID0gc2VsZWN0KGRhdGFmcmFtZSwgLW9uZV9vZigib3V0Y29tZSIpKQ0KfQ0KICBpZiAoInhpc3QiICVpbiUgY29sbmFtZXMoZGF0YWZyYW1lKSAmJiAiZWlmMWF5IiAlaW4lIGNvbG5hbWVzKGRhdGFmcmFtZSkgJiYgImFua3JkNDQiICVpbiUgY29sbmFtZXMoZGF0YWZyYW1lKSkgew0KICAgIG91dGNvbWVfZGYgPSBkYXRhZnJhbWUgJT4lIHNlbGVjdCh4aXN0LCBlaWYxYXksIGFua3JkNDQpDQogICAgb3V0Y29tZV9kZiA9IGRhdGFmcmFtZSArIDENCiAgICBvdXRjb21lX2RmID0gbG9nKG91dGNvbWVfZGYpDQogICAgb3V0Y29tZV9kZiA9IHBhaXJ3aXNlX2NvbF9kaWZmKG91dGNvbWVfZGYpICU+JSBhcy5tYXRyaXgoKQ0KICAgIG91dGNvbWVfZGYgPSBkYXRhLmZyYW1lKG91dGNvbWVfZGYpDQogICAgDQogICAgIyBDYW4gcmVwbGFjZSB0aGlzIHdpdGggYW4gYWxyZWFkeSBwcmVwcm9jZXNzZWQgZGF0YWZyYW1lDQogICAga25vd25fZ2VuZXMgPSBjKCJ4aXN0IiwgImVpZjFheSIsICJhbmtyZDQ0IikNCiAgICBwX0dTRTQ2NDc0ID0gcERhdGEoR1NFNDY0NzQpDQogICAgcF9HU0U0NjQ3NCRvdXRjb21lID0gaWZlbHNlKHBfR1NFNDY0NzQkY2hhcmFjdGVyaXN0aWNzX2NoMS4xID09ICJTZXg6IE0iLCAwLCAxKQ0KICAgIGV4cHJzX0dTRTQ2NDc0ID0gZGF0YS5mcmFtZSh0KGV4cHJzKEdTRTQ2NDc0KSkpDQogICAgY29sbmFtZXMoZXhwcnNfR1NFNDY0NzQpID0gbG93ZXIoY29sbmFtZXMoZXhwcnNfR1NFNDY0NzQpKQ0KICAgIGV4cHJzX0dTRTQ2NDc0ID0gZXhwcnNfR1NFNDY0NzQgJT4lIHNlbGVjdChrbm93bl9nZW5lcykNCiAgICBleHByc19HU0U0NjQ3NCA9IGV4cHJzX0dTRTQ2NDc0ICsgMQ0KICAgIGV4cHJzX0dTRTQ2NDc0ID0gbG9nKGV4cHJzX0dTRTQ2NDc0KQ0KICAgIGV4cHJzX0dTRTQ2NDc0ID0gcGFpcndpc2UoZXhwcnNfR1NFNDY0NzQpICU+JSBhcy5tYXRyaXgoKQ0KICAgIGV4cHJzX0dTRTQ2NDc0ID0gZGF0YS5mcmFtZShleHByc19HU0U0NjQ3NCkNCiAgICANCiAgICBtb2RlbCA9IGtubihleHByc19HU0U0NjQ3NCwgb3V0Y29tZV9kZiwgcF9HU0U0NjQ3NCRvdXRjb21lLCBrID0gMykNCiAgICANCiAgICBkYXRhZnJhbWUkZ2VuZGVyID0gbW9kZWwNCiAgICBkYXRhZnJhbWUkb3V0Y29tZSA9IG91dGNvbWUNCiAgICANCiAgICByZXR1cm4oZGF0YWZyYW1lKQ0KICAgIA0KICB9DQp9DQpgYGANCg0KYGBge3J9DQojIFNob3cgYm94cGxvdCBmb3IgZXhwcmVzc2lvbiBsZXZlbHMgZm9yIGVhY2ggZ2VuZSBzcGxpdCBieSBzb3VyY2UgZGF0YXNldA0KYGBgDQoNCg0KDQo=